package com.lixw.jdbc.core.dao;

import com.lixw.jdbc.core.wrapper.FieldWrapper;
import com.lixw.jdbc.util.DbUtils;
import com.lixw.jdbc.util.EntityMapperUtils;
import com.lixw.jdbc.util.TableReflectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.lixw.jdbc.core.constant.SqlTemplateConstant.*;

/**
 * @ClassName: DefaultBaseDaoImpl
 * @Description: 公共数据操作方法
 * @Author: xuweiLi
 * @Create: 2025/5/30 16:42
 **/
public abstract class DefaultBaseDaoImpl<T,P> implements BaseDao<T,P>{

    private final TableMetaData<T,P> tableMetaData;

    @SuppressWarnings("unchecked")
    public DefaultBaseDaoImpl() {
        // 获取当前类的泛型父类类型
        Type genericSuperclass = this.getClass().getGenericSuperclass();

        if (genericSuperclass instanceof ParameterizedType parameterizedType) {
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

            Class<T> entityClass = (Class<T>) actualTypeArguments[0];

            Class<P> primaryKeyClass = (Class<P>) actualTypeArguments[1];

            tableMetaData = new DefaultTableMetaDataImpl<>(entityClass,primaryKeyClass);
        } else {
            throw new RuntimeException("泛型解析错误!");
        }
    }

    @Override
    public List<T> list() {
        return this.list(null);
    }

    @Override
    public List<T> list(String whereSql, Object... args) {
        //获取表名
        String tableName = tableMetaData.getTableName();
        String selectSql = String.format(SELECT_TEMPLATE, tableName);

        if(whereSql!=null && !whereSql.isEmpty()){
            selectSql = selectSql + WHERE_TEMPLATE + whereSql;
        }
        //结果集
        try(PreparedStatement preparedStatement = DbUtils.preparedStatement(selectSql)){
            //设置参数
            EntityMapperUtils.setParameters(preparedStatement, args);
            //执行
            ResultSet resultSet = preparedStatement.executeQuery();
            //映射返回
            return EntityMapperUtils.mapToEntityList(tableMetaData.getEntityClass(), resultSet);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public T getOne(String whereSql,Object... args) {
        try {
            String tableName = tableMetaData.getTableName();
            String selectSql = String.format(SELECT_TEMPLATE, tableName);
            selectSql = selectSql + WHERE_TEMPLATE + whereSql;
            List<T> tempList = new ArrayList<>();
            try(PreparedStatement preparedStatement = DbUtils.preparedStatement(selectSql)){
                //设置参数
                EntityMapperUtils.setParameters(preparedStatement, args);
                //执行
                ResultSet resultSet = preparedStatement.executeQuery();
                while(resultSet.next()){
                    T t = EntityMapperUtils.mapToEntity(tableMetaData.getEntityClass(), resultSet);
                    tempList.add(t);
                }

                if(tempList.size()>1){
                    throw new RuntimeException("期望查询一行记录,但结果反回了多行, 查询详情:"+ selectSql +" 参数: "+ Arrays.toString(args));
                }else if(tempList.isEmpty()){
                    return null;
                }
            }
            return tempList.get(0);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public T getById(P id) {
        if (id==null){
            throw new IllegalArgumentException("传入id不能为空");
        }
        try {
            String idName = TableReflectUtils.findIdName(tableMetaData.getEntityClass());
            return this.getOne(idName + " = ?",id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean sava(T t) {
        //获取表名
        String tableName = tableMetaData.getTableName();
        //获取字段个数
        int tableFieldCount = tableMetaData.getTableFieldCount();
        String placeholders = IntStream.range(0, tableFieldCount)
                .mapToObj(item -> "?")
                .collect(Collectors.joining(","));
        String insertSql = String.format(INSERT_TEMPLATE, tableName,placeholders);
        try {
            try(PreparedStatement preparedStatement = DbUtils.preparedStatement(insertSql, Statement.RETURN_GENERATED_KEYS)){
                EntityMapperUtils.setInsertParameters(preparedStatement,tableMetaData.getTableFieldNames(),t);
                //执行新增
                boolean flag = preparedStatement.executeUpdate() > 0;
                // 获取生成的主键
                try (ResultSet rs = preparedStatement.getGeneratedKeys()) {
                    if (rs.next()) {
                        Object generatedId = rs.getObject(1);
                        System.out.println("Generated ID: " + generatedId);
                        String idName = TableReflectUtils.findIdName(tableMetaData.getEntityClass());
                        Field idField = TableReflectUtils.findByColumn(idName, t.getClass());
                        idField.setAccessible(true);
                        Class<?> idType = idField.getType();
                        if(idType == String.class){
                            idField.set(t,generatedId.toString());
                        }else if(idType == Long.class){
                            idField.set(t,Long.valueOf(generatedId.toString()));
                        }else{
                            idField.set(t,Integer.valueOf(generatedId.toString()));
                        }
                    }
                }
                return flag;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public boolean updateById(T obj) {
        if (obj==null){
            throw new IllegalArgumentException("传入数据不能为空");
        }
        try {
            String idName = TableReflectUtils.findIdName(tableMetaData.getEntityClass());
            Field idField = TableReflectUtils.findByColumn(idName, obj.getClass());
            idField.setAccessible(true);
            return this.update(obj,idName + " = ?",idField.get(obj));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean update(T obj, String whereSql,Object... args) {
        if(whereSql==null || whereSql.trim().isBlank()){
            if(args!=null && args.length > 0){
                throw new IllegalArgumentException("危险的修改操作,请检查是否设置了修改条件!");
            }
            System.err.println("修改全表操作!");
        }else{
            if(args==null || args.length == 0){
                throw new IllegalArgumentException("必须指定参数信息!");
            }
        }
        if(obj==null){
            throw new IllegalArgumentException("修改对象为空");
        }
        //获取表名
        String tableName = tableMetaData.getTableName();
        //获取字段个数
        List<FieldWrapper> tableFieldWrappers = tableMetaData.getTableFieldWrappers(obj);
        if(tableFieldWrappers.isEmpty()){
            throw new IllegalArgumentException("暂无可修改的参数成员");
        }
        List<String> fieldNames = tableFieldWrappers.stream().map(FieldWrapper::getFieldName).toList();

        String placeholders = tableFieldWrappers.stream()
                .map(item -> item.getFieldName()+" = ?")
                .collect(Collectors.joining(","));

        String updateSql = String.format(UPDATE_TEMPLATE, tableName,placeholders);
        if(whereSql!=null){
            updateSql = updateSql + WHERE_TEMPLATE + whereSql;
        }
        System.out.println(updateSql);
        try {
            try(PreparedStatement preparedStatement = DbUtils.preparedStatement(updateSql)){
                EntityMapperUtils.setUpdateParameters(preparedStatement,fieldNames,obj,args);
                return preparedStatement.executeUpdate() > 0;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean deleteById(P id) {
        if (id==null){
            throw new IllegalArgumentException("待删除id不能为空");
        }
        try {
            String idName = TableReflectUtils.findIdName(tableMetaData.getEntityClass());
            return this.delete(idName + " = ?",id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean delete(String whereSql, Object... args) {
        if(whereSql==null || whereSql.trim().isBlank()){
            if(args!=null && args.length > 0){
                throw new IllegalArgumentException("危险的删除操作,这样做会把整表数据删除 请检查条件!!");
            }
            System.err.println("删除全表操作!");
        }else{
            if(args==null || args.length == 0){
                throw new IllegalArgumentException("必须指定参数信息!");
            }
        }
        //获取表名
        String tableName = tableMetaData.getTableName();
        //获取字段个数
        String deleteSql = String.format(DELETE_TEMPLATE, tableName);
        if(whereSql!=null){
            deleteSql = deleteSql + WHERE_TEMPLATE + whereSql;
        }
        System.out.println(deleteSql);
        try {
            try(PreparedStatement preparedStatement = DbUtils.preparedStatement(deleteSql)){
                if(whereSql!=null && args!=null && args.length>0){
                    EntityMapperUtils.setParameters(preparedStatement,args);
                }
                return preparedStatement.executeUpdate() > 0;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public long count(String whereSql, Object... args) {
        //获取表名
        String tableName = tableMetaData.getTableName();
        String selectSql = String.format(SELECT_COUNT_TEMPLATE, tableName);
        if(whereSql!=null && !whereSql.isEmpty()){
            selectSql = selectSql + WHERE_TEMPLATE + whereSql;
        }
        //结果集
        try(PreparedStatement preparedStatement = DbUtils.preparedStatement(selectSql)){
            //设置参数
            EntityMapperUtils.setParameters(preparedStatement, args);
            //执行
            ResultSet resultSet = preparedStatement.executeQuery();
            resultSet.next();
            return resultSet.getLong(1);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

/*    @Override
    public Map<Object,Object> queryMap(String sql, Object... args) {
        Map<Object, Object> map = new HashMap<>();
        //结果集
        try (PreparedStatement preparedStatement = DbUtils.preparedStatement(sql)) {
            //设置参数
            EntityMapperUtils.setParameters(preparedStatement, args);
            //执行
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {//while循环循环一次，代表一行
                Object key = resultSet.getObject(1);
                Object value = resultSet.getObject(2);
                map.put(key, value);
            }
            return map;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Object> queryList(String sql, Object... args) {
        List<Object> list = new ArrayList<>();
        //结果集
        try (PreparedStatement preparedStatement = DbUtils.preparedStatement(sql)) {
            //设置参数
            EntityMapperUtils.setParameters(preparedStatement, args);
            //执行
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {//while循环循环一次，代表一行
                list.add(resultSet.getObject(1));
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }*/
}